package com.gitee.wsl.compose.chart


import androidx.compose.animation.core.AnimationSpec
import androidx.compose.animation.core.spring
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.ReadOnlyComposable
import androidx.compose.runtime.staticCompositionLocalOf
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.SolidColor
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import com.gitee.wsl.common.ui.draw.style.LineStyle
import com.gitee.wsl.compose.chart.xy.axis.style.TickPosition
import com.gitee.wsl.compose.chart.legend.LegendLocation

/**
 * KiwkCharts components use values provided here when retrieving default values.
 *
 * Use this to configure the overall theme of elements within this KoalaPlotTheme.
 *
 * Any values that are not set will inherit the current value from the theme, falling back to the
 * defaults if there is no parent KoalaPlotTheme. This allows using a KoalaPlotTheme at the top
 * of your application, and then separate KoalaPlotTheme(s) for different screens / parts of your
 * UI, overriding only the parts of the theme definition that need to change.
 *
 * @param plotSizes Defines sizes for various elements
 * @param animationSpec How graph generation should be animated
 * @param axisThemeStyle Axis and grid visual characteristics
 * @param legendLocation Where legends should be located within Charts
 */
@Composable
 fun KoalaPlotTheme(
    plotSizes: PlotSizes = KoalaPlotTheme.plotSizes,
    animationSpec: AnimationSpec<Float> = KoalaPlotTheme.animationSpec,
    axisThemeStyle: AxisThemeStyle = KoalaPlotTheme.axisThemeStyle,
    //legendLocation: LegendLocation = KoalaPlotTheme.legendLocation,
    content: @Composable () -> Unit
) {
    CompositionLocalProvider(
        LocalPlotSizes provides plotSizes,
        LocalAnimationSpec provides animationSpec,
        LocalAxisThemeStyle provides axisThemeStyle,
        //LocalLegendLocation provides legendLocation
    ) {
        content()
    }
}

/**
 * Contains functions to access the current theme values provided at the call site's position in
 * the hierarchy.
 */
 object KoalaPlotTheme {
     val plotSizes: PlotSizes
        @Composable
        @ReadOnlyComposable
        get() = LocalPlotSizes.current

     val animationSpec: AnimationSpec<Float>
        @Composable
        @ReadOnlyComposable
        get() = LocalAnimationSpec.current

     val axisThemeStyle: AxisThemeStyle
        @Composable
        @ReadOnlyComposable
        get() = LocalAxisThemeStyle.current

     val legendLocation: LegendLocation
        @Composable
        @ReadOnlyComposable
        get() = LocalLegendLocation.current
}

/**
 * Theme sizes.
 *
 * @property symbol The size for symbols
 * @property gap The size of gaps, margins, and padding
 */
 data class PlotSizes(
    val symbol: Dp = 8.dp,
    val gap: Dp = 8.dp,
    val barWidth: Float = 0.8f
)

/**
 * CompositionLocal used to pass [AxisThemeStyle] theme properties down the tree.
 *
 * Setting the value here is typically done as part of [KoalaPlotTheme].
 * To retrieve the current value of this CompositionLocal, use [KoalaPlotTheme.axisThemeStyle].
 */
internal val LocalPlotSizes = staticCompositionLocalOf { PlotSizes() }

/**
 * Theme properties for Axes and grid lines.
 *
 * @property color Axis color
 * @property majorTickSize The length of major tick marks
 * @property minorTickSize The length of minor tick marks
 * @property lineThickness The line thickness of axes
 * @property majorGridlineStyle The style for major gridlines, set to null to turn off
 * @property minorGridlineStyle The style for minor gridlines, set to null to turn off
 */
 data class AxisThemeStyle(
    val color: Color = Color.LightGray,
    val majorTickSize: Dp = 7.dp,
    val minorTickSize: Dp = 3.dp,
    val lineThickness: Dp = 0.dp,
    val tickPosition: TickPosition = TickPosition.Outside,
    val majorGridlineStyle: LineStyle? = LineStyle(
        SolidColor(Color.LightGray),
        strokeWidth = 0.dp
    ),
    val minorGridlineStyle: LineStyle? = LineStyle(
        SolidColor(Color.LightGray),
        strokeWidth = 0.dp
    )
)

internal val LocalAxisThemeStyle = staticCompositionLocalOf { AxisThemeStyle() }

internal val LocalAnimationSpec = staticCompositionLocalOf<AnimationSpec<Float>> { spring(2f) }

internal val LocalLegendLocation = staticCompositionLocalOf { LegendLocation.LEFT }

internal const val DegreesFullCircle = 360.0f

/**
 * ColorPaletteGenerator will create [count] colors.
 */
 typealias ColorPaletteGenerator = (count: Int) -> List<Color>

/**
 * Will generate a color palette that varies the hue in even increments to obtain
 * [count] colors. It uses the HSL model with the ability to separately specify
 * the [saturation] and [lightness] of the palette colors.
 */
fun generateHueColorPalette(
    count: Int,
    saturation: Float = 0.5f,
    lightness: Float = 0.5f
): List<Color> {
    val delta = (DegreesFullCircle / count)

    return buildList {
        for (i in 0 until count) {
            add(Color.hsl((delta * i), saturation, lightness))
        }
    }
}